# -*- coding: utf-8 -*-

from odoo import models, fields, api, _
from odoo.exceptions import UserError


class CpqCostModel(models.Model):
    _name = 'cpq.cost.model'
    _description = '成本模型'
    _rec_name = 'name'
    
    # ============ 基础信息 ============
    name = fields.Char(
        string='成本模型名称',
        compute='_compute_name',
        store=True
    )
    
    quotation_id = fields.Many2one(
        'cpq.quotation',
        string='报价单'
    )
    
    product_id = fields.Many2one(
        'product.product',
        string='产品',
        required=True
    )
    
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        default=lambda self: self.env.company
    )
    
    currency_id = fields.Many2one(
        'res.currency',
        related='company_id.currency_id',
        string='货币'
    )
    
    # ============ 产量假设 ============
    estimated_quantity = fields.Float(
        string='预计总产量',
        required=True,
        default=100000.0
    )
    
    annual_quantity = fields.Float(
        string='年度产量'
    )
    
    lifecycle_years = fields.Float(
        string='项目生命周期(年)',
        default=5.0
    )
    
    # ============ 成本构成(自动计算) ============
    material_cost = fields.Monetary(
        string='物料成本',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    tooling_cost_per_unit = fields.Monetary(
        string='单件工装摊销',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    manufacturing_cost = fields.Monetary(
        string='制造加工成本',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    labor_cost = fields.Monetary(
        string='人工成本',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    overhead_cost = fields.Monetary(
        string='管理费用',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    quality_cost = fields.Monetary(
        string='质量成本',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    packaging_cost = fields.Monetary(
        string='包装物流成本',
        compute='_compute_costs',
        store=True,
        currency_field='currency_id'
    )
    
    total_cost = fields.Monetary(
        string='总成本',
        compute='_compute_total_cost',
        store=True,
        currency_field='currency_id'
    )
    
    # ============ 成本明细行 ============
    cost_line_ids = fields.One2many(
        'cpq.cost.line',
        'cost_model_id',
        string='成本明细'
    )
    
    # ============ 备注 ============
    notes = fields.Text(
        string='备注'
    )
    
    # ============ 计算名称 ============
    @api.depends('quotation_id', 'product_id')
    def _compute_name(self):
        """生成成本模型名称"""
        for record in self:
            if record.quotation_id:
                record.name = f'{record.quotation_id.number} - 成本模型'
            elif record.product_id:
                record.name = f'{record.product_id.name} - 成本模型'
            else:
                record.name = '成本模型'
    
    # ============ 核心成本计算 ============
    @api.depends('cost_line_ids', 'cost_line_ids.subtotal', 'estimated_quantity')
    def _compute_costs(self):
        """核心成本计算算法"""
        for record in self:
            # 1. 物料成本计算(含损耗)
            material_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'material'
            )
            material_cost = 0
            for line in material_lines:
                # 公式: 物料成本 = 单价 × 用量 × (1 + 损耗率)
                effective_qty = line.quantity * (1 + line.waste_rate / 100)
                material_cost += line.unit_cost * effective_qty
            record.material_cost = material_cost
            
            # 2. 工装摊销计算
            tooling_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'tooling' and l.is_amortized
            )
            tooling_cost_per_unit = 0
            for line in tooling_lines:
                if line.amortization_quantity > 0:
                    # 公式: 单件摊销 = 工装总成本 ÷ 预计总产量
                    tooling_cost_per_unit += line.total_tooling_cost / line.amortization_quantity
            record.tooling_cost_per_unit = tooling_cost_per_unit
            
            # 3. 制造加工成本
            process_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'process'
            )
            record.manufacturing_cost = sum(process_lines.mapped('subtotal'))
            
            # 4. 人工成本
            labor_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'labor'
            )
            record.labor_cost = sum(labor_lines.mapped('subtotal'))
            
            # 5. 质量成本
            quality_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'quality'
            )
            record.quality_cost = sum(quality_lines.mapped('subtotal'))
            
            # 6. 包装物流成本
            packaging_lines = record.cost_line_ids.filtered(
                lambda l: l.cost_type == 'packaging'
            )
            record.packaging_cost = sum(packaging_lines.mapped('subtotal'))
            
            # 7. 间接费用(按制造成本和人工成本的一定比例)
            overhead_rate = record.company_id.partner_id.property_product_category.overhead_allocation_rate or 15.0
            if overhead_rate > 0:
                overhead_base = record.manufacturing_cost + record.labor_cost
                record.overhead_cost = overhead_base * (overhead_rate / 100)
            else:
                # 如果没有设置分摊率，直接汇总overhead类型的成本行
                overhead_lines = record.cost_line_ids.filtered(
                    lambda l: l.cost_type == 'overhead'
                )
                record.overhead_cost = sum(overhead_lines.mapped('subtotal'))
    
    @api.depends('material_cost', 'tooling_cost_per_unit', 'manufacturing_cost',
                 'labor_cost', 'overhead_cost', 'quality_cost', 'packaging_cost')
    def _compute_total_cost(self):
        """计算总成本"""
        for record in self:
            record.total_cost = (
                record.material_cost +
                record.tooling_cost_per_unit +
                record.manufacturing_cost +
                record.labor_cost +
                record.overhead_cost +
                record.quality_cost +
                record.packaging_cost
            )
    
    # ============ 业务方法 ============
    def _generate_cost_lines(self):
        """根据产品配置自动生成成本明细"""
        self.ensure_one()
        
        # 清除现有成本明细
        self.cost_line_ids.unlink()
        
        # TODO: 这里需要根据产品配置和BOM生成成本明细
        # 示例: 创建基础成本项
        
        # 如果有配置，根据配置生成
        if self.quotation_id and self.quotation_id.configuration_id:
            self._generate_from_configuration()
        
        # 如果有BOM，根据BOM生成物料成本
        if self.quotation_id and self.quotation_id.configuration_id and \
           self.quotation_id.configuration_id.validated_bom_id:
            self._generate_from_bom()
    
    def _generate_from_configuration(self):
        """根据配置生成成本"""
        config = self.quotation_id.configuration_id
        
        # 从配置项中提取成本影响
        for config_line in config.attribute_line_ids:
            if config_line.cost_impact != 0:
                self.env['cpq.cost.line'].create({
                    'cost_model_id': self.id,
                    'cost_type': 'other',
                    'name': f'{config_line.attribute_id.name}: {config_line.value_id.name}',
                    'unit_cost': config_line.cost_impact,
                    'quantity': 1.0,
                    'description': f'配置项成本影响'
                })
    
    def _generate_from_bom(self):
        """根据BOM生成物料成本"""
        bom = self.quotation_id.configuration_id.validated_bom_id
        
        for bom_line in bom.bom_line_ids:
            self.env['cpq.cost.line'].create({
                'cost_model_id': self.id,
                'cost_type': 'material',
                'name': bom_line.product_id.name,
                'product_id': bom_line.product_id.id,
                'unit_cost': bom_line.product_id.standard_price,
                'quantity': bom_line.product_qty,
                'waste_rate': 5.0,  # 默认5%损耗率
                'description': f'物料清单组件'
            })
    
    def action_add_cost_line(self):
        """手动添加成本项"""
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': '添加成本项',
            'res_model': 'cpq.cost.line',
            'view_mode': 'form',
            'target': 'new',
            'context': {'default_cost_model_id': self.id}
        }
    
    def action_recalculate(self):
        """重新计算成本"""
        self.ensure_one()
        # 触发计算字段重算
        self._compute_costs()
        self._compute_total_cost()
        
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': '重新计算完成',
                'message': f'总成本: {self.total_cost:.2f}',
                'type': 'success',
                'sticky': False,
            }
        }

